1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2014 Devisualization (Richard Andrew Cattermole)
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 module devisualization.window.context.opengl;
25 import devisualization.window.window;
26 import devisualization.window.interfaces.context;
27 
28 import derelict.opengl3.gl;
29 import derelict.opengl3.wgl;
30 import derelict.opengl3.wglext;
31 
32 private {
33     bool loadedDGL;
34 }
35 
36 class OpenglContext : IContext {
37     private {
38         HDC hdc_;
39         HGLRC hglrc_;
40     }
41 
42     this(Window window, WindowConfig config) {
43         if (!loadedDGL) {
44             DerelictGL.load();
45             loadedDGL = true;
46         }
47 
48         import windows : GetDC;
49         hdc_ = GetDC(window.hwnd);
50 
51         configurePixelFormat(window, config, hdc_);
52 
53         hglrc_ = cast(HGLRC)wglCreateContext(hdc_);
54         activate();
55     }
56 
57     @property {
58         void activate() {
59             wglMakeCurrent(hdc_, hglrc_);
60             DerelictGL.reload();
61         }
62 
63         void destroy() {
64             wglDeleteContext(hglrc_);
65         }
66 
67         void swapBuffers() {
68 			glFlush();
69 			SwapBuffers(hdc_);
70         }
71 
72         WindowContextType type() { return WindowContextType.Opengl; }
73 
74         string toolkitVersion() {
75             char[] str;
76             const(char*) c = glGetString(GL_VERSION);
77             size_t i;
78 
79             if (c !is null) {
80                 while (c[i] != '\0') {
81                     str ~= c[i];
82                     i++;
83                 }
84             }
85 
86             return str.idup;
87         }
88 
89         string shadingLanguageVersion() {
90             char[] str;
91             const(char*) c = glGetString(GL_SHADING_LANGUAGE_VERSION);
92             size_t i;
93             
94             if (c !is null) {
95                 while (c[i] != '\0') {
96                     str ~= c[i];
97                     i++;
98                 }
99             }
100             
101             return str.idup;
102         }
103 
104         string[] extensions() {
105             string[] ret;
106 
107             char[] str;
108             const(char*) c = glGetString(GL_SHADING_LANGUAGE_VERSION);
109             size_t i;
110             
111             if (c !is null) {
112                 while (c[i] != '\0') {
113                     if (c[i] == ' ') {
114                         ret ~= str.idup;
115                         str.length = 0;
116                     } else {
117                         str ~= c[i];
118                     }
119                     i++;
120                 }
121             }
122             
123             return ret;
124         }
125     }
126 }
127 
128 private {
129     import windows : SwapBuffers, HDC, HGLRC;
130 
131     void configurePixelFormat(Window window, WindowConfig config, HDC hdc_) {
132         import windows : PIXELFORMATDESCRIPTOR, ChoosePixelFormat, SetPixelFormat, PFD_DRAW_TO_WINDOW, PFD_SUPPORT_OPENGL, PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, PFD_MAIN_PLANE;
133         PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR( 
134             PIXELFORMATDESCRIPTOR.sizeof,
135                 1,                     // version number  
136                 PFD_DRAW_TO_WINDOW |   // support window  
137                 PFD_SUPPORT_OPENGL |   // support OpenGL  
138                 PFD_DOUBLEBUFFER,      // double buffered  
139                 PFD_TYPE_RGBA,         // RGBA type  
140                 24,                    // 24-bit color depth  
141                 0, 0, 0, 0, 0, 0,      // color bits ignored  
142                 0,                     // no alpha buffer  
143                 0,                     // shift bit ignored  
144                 0,                     // no accumulation buffer  
145                 0, 0, 0, 0,            // accum bits ignored  
146                 32,                    // 32-bit z-buffer  
147                 8,                     // 8-bit stencil buffer  
148                 0,                     // no auxiliary buffer  
149                 PFD_MAIN_PLANE,        // main layer  
150                 0,                     // reserved  
151                 0, 0, 0                // layer masks ignored  
152           );
153                                                           
154         int  iPixelFormat; 
155         
156         // get the best available match of pixel format for the device context   
157         iPixelFormat = ChoosePixelFormat(hdc_, &pfd); 
158         
159         // make that the pixel format of the device context  
160         SetPixelFormat(hdc_, iPixelFormat, &pfd);
161     }
162 }